package com.zhiwei.popup;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.Locale;

/**
 * Created by zhiwei on 2018/1/27.
 */

public class ColorPickerView extends View {

    private int pcWidth;
    private int pcHeight;
    private int cpoWidth;
    private int cpoHeight;
    private int cpHeight;
    private int cpWidth;
    private Rect colorPickerSrc;
    private RectF colorPickerDst;
    private Rect paletterColorSrc;
    private RectF paletterColorDst;

    private int paletteSize;
    private final int defaultPaletteSize = 250;
    private float colorPickerSizeOffset = 16;
    private int x;
    private int y;
    private float scale;
    private int pixelX;
    private int pixelY;

    public ColorPickerView(Context context) {
        super(context);
    }

    public ColorPickerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public ColorPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    private OnColorChangedListener onColorChangedListener;
    private Bitmap colorPicker;  // 165 x 165
    private Bitmap paletterColor;// 500 x 500
    private Bitmap colorPickerOverlay; // 300 x 300

    private Paint backgroundPaint; // 背景画笔
    private Paint pointPaint; // 背景画笔

    private Rect colorPickerOverlaySrc;//绘画Bitmap的区域
    private RectF colorPickerOverlayDst;//显示Bitmap的区域

    private void init(AttributeSet attrs) {
        TypedArray types = getContext().obtainStyledAttributes(attrs,
                R.styleable.ColorPickerView);
        try {
            paletteSize = types.getDimensionPixelSize(R.styleable.ColorPickerView_circleSize, defaultPaletteSize);
        } finally {
            types.recycle(); // TypeArray用完需要recycle
        }
        colorPicker = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.color_picker);
        paletterColor = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.palettecolor);
        colorPickerOverlay = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.color_picker_overlay);

        pcWidth = paletterColor.getWidth();
        pcHeight = paletterColor.getHeight();
        cpoWidth = colorPickerOverlay.getWidth();
        cpoHeight = colorPickerOverlay.getHeight();
        cpWidth = colorPicker.getWidth();
        cpHeight = colorPicker.getHeight();

        scale = (paletteSize * 1.0f) / (pcWidth * 1.0f);

        backgroundPaint = new Paint();
        backgroundPaint.setAntiAlias(true);
        pointPaint = new Paint();
        pointPaint.setColor(Color.RED);
        pointPaint.setStrokeWidth(3);

        paletterColorSrc = new Rect(0, 0, pcWidth, pcHeight);
        paletterColorDst = new RectF(0, 0, pcWidth * scale, pcHeight * scale);
//                      25              15              5               2
        float lt = (pcHeight / 2 - cpoHeight / 2 + cpHeight / 4) * scale; // = 100
        float rb = (pcHeight / 2 + cpoHeight / 2 - cpHeight / 4) * scale; // = 400
        colorPickerOverlaySrc = new Rect(0, 0, cpoWidth, cpoHeight);
        colorPickerOverlayDst = new RectF(lt, lt, rb, rb);
        colorPickerSizeOffset = colorPickerSizeOffset * scale;
        lt = (pcHeight / 2 - cpHeight / 2) * scale;  // = 167
        rb = (pcHeight / 2 + cpHeight / 2) * scale;  // = 333
        colorPickerSrc = new Rect(0, 0, cpWidth, cpHeight);
        colorPickerDst = new RectF(colorPickerSizeOffset, lt + colorPickerSizeOffset,
                cpWidth * scale - colorPickerSizeOffset, rb - colorPickerSizeOffset);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

//        canvas.drawRect(0, 0, 300, 300, backgroundPaint);
        canvas.drawBitmap(paletterColor, paletterColorSrc, paletterColorDst, backgroundPaint);
        canvas.drawBitmap(colorPickerOverlay, colorPickerOverlaySrc, colorPickerOverlayDst, backgroundPaint);

        if (!isChooseGray && (x > 0 || y > 0)) {
            colorPickerDst.left = x + colorPickerSizeOffset;
            colorPickerDst.top = y + colorPickerSizeOffset;
            colorPickerDst.right = x + (cpWidth * scale - colorPickerSizeOffset);
            colorPickerDst.bottom = y + (cpHeight * scale - colorPickerSizeOffset);
        }

        canvas.drawPoint(pixelX , pixelY , pointPaint);

        canvas.drawBitmap(colorPicker, colorPickerSrc, colorPickerDst, backgroundPaint);
    }

    private void moveColorSelector(MotionEvent event) {

        float centerX = pcWidth * scale / 2;
        float centerY = pcHeight * scale / 2;

        float dx = event.getX() - centerX;
        float dy = event.getY() - centerY;

        float angle = (float) Math.atan2(dy, dx);
        float angleDeg = (float) (Math.toDegrees(angle) + 180);
        float percetage = angleDeg / 360.0f;

        angleDeg = (percetage * 360.0f) - 180.0f;
        angle = (float) Math.toRadians(angleDeg);

        float limit = cpWidth * scale;

        x = (int) (centerX + (limit * Math.cos(angle)) - cpWidth / 2 * scale);
        y = (int) (centerX + (limit * Math.sin(angle)) - cpWidth / 2 * scale);

        pixelX = (int) (centerX + (limit * Math.cos(angle)));
        pixelY = (int) (centerX + (limit * Math.sin(angle)));

        if (onColorChangedListener != null) {
            int color = paletterColor.getPixel(pixelX, pixelY);
            onColorChangedListener.onColorChange(
                    Color.red(color), Color.green(color), Color.blue(color), color);
        }

//        Math.atan
    }

    boolean isChooseGray;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (MotionEvent.ACTION_MOVE == event.getAction()) {
            if (!isChooseGray) {
                moveColorSelector(event);
            } else {
                moveGraySelector(event);
            }
        } else if (MotionEvent.ACTION_DOWN == event.getAction()) {
            isInGrayOrColorArea(event);

        }
        invalidate();
        return true;
    }

    private void isInGrayOrColorArea(MotionEvent event) {
        float centerX = pcWidth * scale / 2;
        float centerY = pcHeight * scale / 2;

        float dx = Math.abs(event.getX() - centerX);
        float dy = Math.abs(event.getY() - centerY);

        int distance = (int) Math.sqrt(dx * dx + dy * dy);
        int radius = (int) (cpoWidth * scale / 4);
        if (distance <= radius) {
            isChooseGray = true;
        } else {
            isChooseGray = false;
        }
    }

    private void moveGraySelector(MotionEvent event) {
        float centerX = paletteSize / 2;
        float centerY = paletteSize / 2;

        float dx = event.getX() - centerX;
        float dy = event.getY() - centerY;

        int distance = (int) Math.sqrt(dx * dx + dy * dy);
        int radius = (int) (colorPickerOverlayDst.height() / 2);
        if (distance > radius) {
            float angle = (float) Math.acos(dx / distance);
            angle = angle * (event.getY() < centerY ? -1 : 1);
            x = (int) (centerX + (radius * Math.cos(angle)));
            y = (int) (centerX + (radius * Math.sin(angle)));
        } else {
            x = (int) (event.getX());
            y = (int) (event.getY());
        }
        int grayCircleTop2Border = (int) (centerY - radius - 1);
        float grayScale = ((y - grayCircleTop2Border) / colorPickerOverlayDst.height());
        grayScale = 1 - grayScale; //revert
        int gray = (int) (grayScale * 255);
        if (onColorChangedListener != null) {
            int color = Color.rgb(gray , gray, gray);
            onColorChangedListener.onColorChange(
                    Color.red(color), Color.green(color), Color.blue(color), color);
        }

        System.out.println("grayScale " + grayScale + " y - grayCircleTop2Border " + (y - grayCircleTop2Border));
        System.out.println("x  " + x + "  y " + y);
    }


    public void setOnColorChangedListener(OnColorChangedListener onColorChangedListener) {
        this.onColorChangedListener = onColorChangedListener;
    }

    public interface OnColorChangedListener {
        void onColorChange(int r, int g, int b, int color);
    }
}
